package com.io.commonlib.helper

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.Uri
import android.net.wifi.WifiManager
import android.os.Build
import android.provider.MediaStore
import android.provider.Settings
import android.telephony.TelephonyManager
import android.util.DisplayMetrics
import android.view.Display
import androidx.core.content.FileProvider
import com.io.commonlib.enum.NetworkType
import java.io.*
import java.lang.reflect.Field
import java.net.InetAddress
import java.net.NetworkInterface
import java.util.*
import java.util.regex.Pattern

/**
 * Description: 通用设备信息的获取
 * 2020-07-29 16:37
 * @author LiuMin
 */
class CommonDeviceHelper {
    private val TAG = CommonDeviceHelper::class.java.simpleName

    /**
     * 获取设备mac
     */
    fun getDeviceMac(ctx: Context): String {
        var mac = ""
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            mac = getDeviceMacBefore6(ctx)
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && Build.VERSION.SDK_INT < Build.VERSION_CODES.N
        ) {
            mac = getDeviceMacBefore7(ctx)
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mac = getDeviceMacAfter7(ctx)
        }
        return mac
    }

    /**
     * 获取设备IP
     */
    fun getDeviceIp(ctx: Context): String {
        var enumeration: Enumeration<NetworkInterface>? = NetworkInterface.getNetworkInterfaces()
        enumeration?.let {
            while (it.hasMoreElements()) {
                val nif = it.nextElement()
                val iNetAddresses =
                    nif.inetAddresses
                iNetAddresses?.let { it0 ->
                    while (it0.hasMoreElements()) {
                        val iNetAddress = it0.nextElement()
                        if (!iNetAddress.isLoopbackAddress && isIPv4Address(iNetAddress.hostAddress)) {
                            return iNetAddress.hostAddress.toString()
                        }
                    }
                }
            }
        }
        return ""
    }

    /**
     * 获取设备IP
     */
    fun getDeviceInetAddress(ctx: Context): InetAddress? {
        var enumeration: Enumeration<NetworkInterface>? = NetworkInterface.getNetworkInterfaces()
        enumeration?.let {
            while (it.hasMoreElements()) {
                val nif = it.nextElement()
                val iNetAddresses =
                    nif.inetAddresses
                iNetAddresses?.let { it0 ->
                    while (it0.hasMoreElements()) {
                        val iNetAddress = it0.nextElement()
                        if (!iNetAddress.isLoopbackAddress && isIPv4Address(iNetAddress.hostAddress)) {
                            return iNetAddress
                        }
                    }
                }
            }
        }
        return null
    }

    /**
     * 获取网络是否可用
     */
    fun getNetworkStatus(ctx: Context): NetworkType {
        var result = NetworkType.Null
        val cm = ctx.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            cm?.run {
                cm.getNetworkCapabilities(cm.activeNetwork)?.run {
                    result = when {
                        hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkType.Wifi
                        hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkType.Cellular
                        hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> NetworkType.Ethernet
                        hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> NetworkType.VPN
                        else -> NetworkType.Null
                    }
                }
            }
        } else {
            cm?.run {
                cm.activeNetworkInfo?.run {
                    if (type == ConnectivityManager.TYPE_WIFI) {
                        result = NetworkType.Wifi
                    } else if (type == ConnectivityManager.TYPE_MOBILE) {
                        result = NetworkType.Cellular
                    }
                }
            }
        }
        return result
    }

    /**
     * 获取设备id
     */
    fun getDeviceId(ctx: Context): String {
        val tm = ctx.getSystemService(Activity.TELEPHONY_SERVICE)
                as TelephonyManager
        tm?.let {
            return Settings.Secure.getString(ctx.contentResolver, Settings.Secure.ANDROID_ID)
        }
        return ""
    }

    /**
     * 获取手机卡的序列号
     */
    fun getSimSerialNumber(context: Context): String {
        val telephonyManager =
            context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        telephonyManager?.let {
            val serialNum = telephonyManager.simSerialNumber
            serialNum?.let {
                return serialNum
            }
            return ""
        }
        return ""
    }

    /**
     * 设备是否已经root
     */
    fun isRoot(): Boolean {
        val binPath = "/system/bin/su"
        val xBinPath = "/system/xbin/su"
        if (File(binPath).exists() && isExecutable(binPath)) {
            return true
        }
        if (File(xBinPath).exists() && isExecutable(xBinPath)) {
            return true
        }
        return false
    }

    /**
     * 判断是否安装了指定的应用
     */
    fun isInstalledApp(ctx: Context, packageName: String): Boolean {
        val packageManager = ctx.packageManager
        try {
            val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_GIDS)
            packageInfo?.let {
                return true
            } ?: let {
                return false
            }
        } catch (e: Exception) {
            return false
        }
    }

    /**
     * 通过ping指定网页确定网络是否是真的可用
     */
    fun pingWeb(webPage: String, pingNum: Int): Boolean {
        return try {
            val p = Runtime.getRuntime()
                .exec("/system/bin/ping -c $pingNum $webPage")
            val status = p.waitFor()
            if (status == 0) {
                true
            } else {
                false
            }
        } catch (e: IOException) {
            false
        } catch (e: InterruptedException) {
            false
        }
    }

    /**
     * 获取设备序列号
     */
    fun getSerialNum(): String {
        var result = ""
        try {
            val c = Class.forName("android.os.SystemProperties")
            val get = c.getMethod("get", String::class.java)
            result = get.invoke(c, "ro.serialno") as String
        } catch (e: Exception) {
            LogHelper.e(TAG, "getSerialNum--Exception:${e.message}")
        }
        return result
    }

    /**
     * 获取状态栏高度
     *
     * @param context
     * @return
     */
    fun getStatusBarHeight(context: Context): Int {
        val c: Class<*>
        val obj: Any
        val field: Field
        val x: Int
        try {
            c = Class.forName("com.android.internal.R\$dimen")
            obj = c.newInstance()
            field = c.getField("status_bar_height")
            x = field[obj].toString().toInt()
            return context.resources
                .getDimensionPixelSize(x)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return 0
    }

    /**
     * 获取屏幕的DPI
     */
    fun getDeviceDpi(context: Context): Float {
        val displayMatrics = DisplayMetrics()
        context.display?.let {
            it.getRealMetrics(displayMatrics)
            return displayMatrics.density
        } ?: let { return -1f }
    }

    /**
     * 调用相机拍照，并保存拍摄照片
     * [filePath]--拍照后图片的保存路径
     */
    fun openCameraAndSaveImage(context: Activity, filePath: String, requestCode: Int) {
        try {
            val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
            var photoUri: Uri
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
                photoUri = FileProvider.getUriForFile(
                    context,
                    "${context.applicationInfo.packageName}.provider", File(filePath)
                )
            } else {
                photoUri = Uri.fromFile(File(filePath))
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
            context.startActivityForResult(intent, requestCode)
        } catch (e: Exception) {
            LogHelper.d(TAG, "openCameraAndSaveImage--${e.message}")
        }
    }

    /**
     * 从系统相册选择照片
     */
    fun getPhotoFromSysAlbum(context: Activity, requestCode: Int) {
        context.startActivityForResult(
            Intent(
                Intent.ACTION_PICK,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI
            ), requestCode
        )
    }

    /**
     * 获取屏幕的宽度--单位px
     */
    fun getDeviceWidthPixels(context: Context): Int {
        val displayMatrics = DisplayMetrics()
        context.display?.let {
            it.getRealMetrics(displayMatrics)
            return displayMatrics.widthPixels
        } ?: let { return -1 }
    }

    //region 私有方法
    /**
     * Check if valid IPV4 address.
     *
     * @param input the address string to check for validity.
     *
     * @return True if the input parameter is a valid IPv4 address.
     */
    private fun isIPv4Address(input: String?): Boolean {
        return ipv4Pattern.matcher(input).matches()
    }

    /**
     * Ipv4 address check.
     */
    private val ipv4Pattern = Pattern.compile(
        "^(" + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" +
                "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
    )

    /**
     * 在6.0以下系统获取设备mac
     */
    private fun getDeviceMacBefore6(context: Context): String {
        var mac = ""
        val wifi = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val info = wifi.connectionInfo
        info?.let {
            mac = info.macAddress
            if (mac.isNotEmpty()) mac = mac.toUpperCase(Locale.ENGLISH)
        }
        return mac
    }

    /**
     * 在6.0以上、7.0以下设备上获取设备mac
     */
    private fun getDeviceMacBefore7(context: Context): String {
        var macSerial = ""
        var str = ""
        val pp = Runtime.getRuntime().exec("cat/sys/class/net/wlan0/address")
        val ir = InputStreamReader(pp.inputStream)
        val input = LineNumberReader(ir)
        while (str != null) {
            str = input.readLine()
            if (str != null) {
                macSerial = str.trim()
                break
            }
        }
        return macSerial
    }

    /**
     * 在7以后的设备中获取设备mac
     */
    private fun getDeviceMacAfter7(context: Context): String {
        val all = Collections.list(NetworkInterface.getNetworkInterfaces())
        for (nif: NetworkInterface in all) {
            if (!nif.name.equals("wlan0", true))
                continue
            val macBytes = nif.hardwareAddress
            macBytes?.let {
                var res1 = StringBuilder()
                for (b: Byte in macBytes) {
                    res1.append(String.format("%02X:", b))
                }
                if (!res1.isNullOrEmpty()) {
                    res1.deleteCharAt(res1.length - 1)
                }
                return res1.toString()
            }
        }
        return ""
    }

    private fun isExecutable(filePath: String): Boolean {
        var process: Process? = null
        try {
            process = Runtime.getRuntime().exec("ls -l $filePath")
            val bufferReader = BufferedReader(InputStreamReader(process.inputStream))
            val str = bufferReader.readLine()
            if (str.isNullOrEmpty() && str.length >= 4) {
                val flag = str[3]
                if (flag == 's' || flag == 'x') return true
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            process?.destroy()
        }
        return false
    }
    //endregion
}